/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.celephais.objectGenerator.fileGenerators;

import com.celephais.objectGenerator.ObjectGenerator;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;

/**
 * @author Eugene Shen
 */
public abstract class FileGenerator {

	protected static final String CRLF = "\r\n";

	protected ObjectGenerator parent;
	protected String pkgName;
	protected String objName;

	public FileGenerator(ObjectGenerator parent) {
		super();
		this.parent = parent;
	}

	public abstract String getTemplateDir();
	public abstract String generateAdditional(String fileContents);
	public abstract String getFileName(String baseClassName);
	public abstract String getOutputDir(String srcDir);

	public boolean generateFile(String srcDir, String pkgName, String objName) {
		this.pkgName = pkgName;
		this.objName = objName;
		
		File dir = null;
		String path = getOutputDir(srcDir);
		if (path != null) {
			dir = new File(path);
			if (!dir.exists() && !dir.mkdirs()) {
				return false;
			}
		}
		else {
			return false;
		}

		String fileContents = readFile(getTemplateDir(), "file.txt");
		if (fileContents.length() == 0) {
			return false;
		}

		// Package Name
		fileContents = fileContents.replaceAll("%pkgName%", pkgName);
		// Class Name
		fileContents = fileContents.replaceAll("%className%", objName);

		// Additional items.  Different subclasses will have different items it
		// needs to generate.
		fileContents = generateAdditional(fileContents);

		String outputFileName = dir.getAbsolutePath() + File.separator + getFileName(objName) + ".java";
		BufferedWriter out = null;
		try {
			out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFileName), "UTF8"));
			out.write(fileContents);
			out.close();
		}
		catch (IOException ex) {
			Logger.getLogger(ObjectGenerator.class.getName()).log(Level.SEVERE, null, ex);
			popErrorDialog("An exception occurred while trying to write to the file: " + outputFileName + ".  Please make sure the file does not exist and try again.");
			return false;
		}

		return true;
	}

	protected String readFile(String dir, String fileName) {
		StringBuilder rtn = new StringBuilder();
		File modelFile = new File(dir + fileName);
		try {
			BufferedReader modelFileIn = new BufferedReader(new InputStreamReader(new FileInputStream(modelFile)));
			String line = modelFileIn.readLine();
			while (line != null) {
				rtn.append(line).append("\r\n");
				line = modelFileIn.readLine();
			}
			modelFileIn.close();
		}
		catch (IOException ex) {
			Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
			popErrorDialog("An error occurred while trying to read the file, " + modelFile.getAbsolutePath());
			return "";
		}
		return rtn.toString();
	}

	protected boolean validateObjName(String name) {
		if (name.length() == 0) {
			popErrorDialog("Please enter a name for your object.");
			return false;
		}
		else {
			char c = name.charAt(0);
			if (c != '_' && !Character.isLetter(c)) {
				popErrorDialog("The object name must begin with either a letter or a _ (underscore).");
				return false;
			}
			else {
				for (int i=1; i<name.length(); ++i) {
					c = name.charAt(i);
					if (c != '_' && !Character.isLetterOrDigit(c)) {
						popErrorDialog("The object name must only contain letters, digits, or _ (underscore).");
						return false;
					}
				}
			}
		}
		return true;
	}

	protected void popErrorDialog(String msg) {
		JOptionPane.showMessageDialog(parent, msg, "Cannot Generate Code", JOptionPane.ERROR_MESSAGE);
	}
}
